#!/bin/bash
#
# Copyright 2015-2017 Adrian DC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

# === Standalone Source Helper ===
# source <(curl -Ls https://github.com/AdrianDC/android_development_shell_tools/raw/master/android_host_common.rc)
# source <(curl -Ls https://github.com/AdrianDC/android_development_shell_tools/raw/master/android_host_grep.rc)

# === Grep Helpers ===
function g()
{
  # Usage: g [inputs] (Grep through sources)

  # Grep through files
  GREP_COLORS='fn=1;1' grep -air --exclude={*.o,*.a,*.cmd,*.ko} --exclude-dir="\.git" --exclude-dir="\.repo" "${*}" .;
}

# === Grep Binaries Helpers ===
function gs()
{
  # Usage: gs [inputs] (Grep through sources and binaries)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . -type f -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    if [ -f "${file}" ]; then
      found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
      if [ ! -z "${found}" ]; then
        echo -e "\e[1;31m${file} :\e[0m ${found}";
      fi;
    fi;
  done;
}

# === Grep Binaries Editor ===
function gce()
{
  # Usage
  if [ -z "${1}" ]; then
    echo '';
    echo ' Usage: gce <inputs> (Grep and edit through sources and binaries)';
    echo '';
    return;
  fi;

  # Variables
  local files=();
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . -type f -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    if [ -f "${file}" ]; then
      found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
      if [ ! -z "${found}" ]; then
        files+=("${file}");
      fi;
    fi;
  done;

  # Edit found files
  fileedit "${files[@]}";
}

# === Grep Kernel Configurations ===
function gck()
{
  # Usage: gck [inputs] (Grep through kernel configurations)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . \( -name 'Kconfig' -o -name 'Makefile' \) -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Android Makefiles ===
function gca()
{
  # Usage: gca [inputs] (Grep through Android makefiles)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . \( -name '*.mk' -o -name '*.bp' -o -name '*.go' \) -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Android Manifests ===
function gcmanifest()
{
  # Usage: gcmanifest [inputs] (Grep through Android Manifests)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . \( -name 'AndroidManifest.xml' \) -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Android .rc Files ===
function gcrc()
{
  # Usage: gcrc [inputs] (Grep through Android .rc files)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . -name '*.rc' -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Android Sepolicies ===
function gcsep()
{
  # Usage: gcsep [inputs] (Grep through Android sepolicies)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . \( -name '*.te' -o -name '*_contexts' \) -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Android .xml Files ===
function gcxml()
{
  # Usage: gcxml [inputs] (Grep through Android .xml files)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . -name '*.xml' -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Android Sepolicies Contexts ===
function gccontexts()
{
  # Usage: gccontexts [inputs] (Grep through Android sepolicies contexts)

  # Variables
  local strings_params;

  # Grep through files
  strings_params="strings $(stringsparams)";
  for file in $(find . -name '*_contexts' -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    found=$(${strings_params} "$(readlink -f "${file}")" | grep -ai "${*}");
    if [ ! -z "${found}" ]; then
      echo -e "\e[1;31m${file} :\e[0m ${found}";
    fi;
  done;
}

# === Grep Search Helpers ===
alias grepi='grep -ai';

# === Grep Android Modules ===
function gcmodules()
{
  # Usage: gcmodules [path] (List all LOCAL_MODULE elements)

  # Variables
  local strings_params;

  # Search all build definitions
  strings_params="strings $(stringsparams)";
  for file in $(find "${1:-.}" \( -name '*.mk' -o -name '*.bp' \) -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    ${strings_params} "$(readlink -f "${file}")" \
      | grep -ai "LOCAL_MODULE[ ]*:=\|LOCAL_PACKAGE_NAME[ ]*:=\|    name: " \
      | sed 's/.*\(:=[ \t]*\|name: "\)\([^"]*\)\(".*\|\)/\2/g';
  done;
}

# === Grep Android Phony ===
function gcphony()
{
  # Usage: gcphony (List all PHONY rules)

  # Variables
  local strings_params;

  # Search all build definitions
  strings_params="strings $(stringsparams)";
  for file in $(find . -name '*.mk' -not -path '*.git/*' -not -path '*.repo/*' -not -path './out/*' | sort); do
    ${strings_params} "$(readlink -f "${file}")" \
      | grep -ai ".PHONY:" \
      | sed 's/.PHONY: //g';
  done;
}

# === Strings Parameters ===
function stringsparams()
{
  # Usage: stringsparams (Get the strings command parameters for variants)

  # Handle Sysinternals strings variant
  if strings -accepteula 2> /dev/null | grep -q 'sysinternals'; then
    echo '-accepteula -nobanner';
    return;
  fi;

  # Handle generic strings variant
  echo '-a';
}
